/*
 Xern Entity Relocation Network
 Copyright (C) 2010-2011 Ronie Salgado <roniesalg@gmail.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
*/

/* -----------------------------------------------------------------------------
 * UString.i
 *
 * MyGUI::UString typemaps for Squirrel
 * ----------------------------------------------------------------------------- */
 
 // This file is an adaptation of std_string.i
 // TODO: Check version of Squirrel.
 
%{
#include "MyGUI_UString.h"
%}

// Treat UString similar to std::string.

/*
Only MyGUI::UString and const MyGUI::UString& are typemaped
they are converted to the Squirrel strings automatically

MyGUI::UString& and MyGUI::UString* are not
they must be explicitly managed (see below)

eg.

MyGUI::UString test_value(MyGUI::UString x) {
   return x;
}

can be used as

s="hello world"
s2=test_value(s)
assert(s==s2)

*/

%naturalvar UString;

/*
Squirrel strings and MyGUI::UString can contain embeded zero's
Therefore a standard out typemap should not be:
  sq_pushstring(L,$1.c_str(), -1);
but
  sq_pushstring(L,$1.data(),$1.size());

Similarly for getting the string
  sq_getstring(v, $input, &temp), $1 = temp;
  
becomes
  sq_getstring(v, $input, &temp), $1.assign(temp,sq_getsize(v,$input));
*/

%typemap(in,checkfn="sqs_isstring") MyGUI::UString (const SQChar *temp)
%{ sq_getstring(v, $input, &temp), $1.assign(temp,sq_getsize(v,$input));%}
%typemap(out) MyGUI::UString (std::string temps)
%{ temps = $1.asUTF8(), sq_pushstring(v,temps.data(),temps.size()); SWIG_arg++;%}

%typemap(in,checkfn="sqs_isstring")	const MyGUI::UString& (const SQChar *tempVal, MyGUI::UString temp)
%{sq_getstring(v, $input, &tempVal), temp.assign(tempVal,sq_getsize(v,$input));$1=&temp;%}

%typemap(out) const MyGUI::UString& (std::string temps)
%{ temps = $1->asUTF8(), sq_pushstring(v,temps.data(),temps.size()); SWIG_arg++;%}

// TODO: Add support for throwing.

// and the typechecks
%typecheck(SWIG_TYPECHECK_STRING) MyGUI::UString,const MyGUI::UString& {
  $1 = sqs_isstring(v,$input);
}

/*
MyGUI::UString& can be wrappered, but you must inform SWIG if it is in or out

eg:
void fn(MyGUI::UString& str);
Is this an in/out/inout value?

Therefore you need the usual
%apply (MyGUI::UString& INOUT) {(MyGUI::UString& str)};
or
%apply MyGUI::UString& INOUT {MyGUI::UString& str};
typemaps to tell SWIG what to do.
*/

%typemap(in) MyGUI::UString &INPUT=const MyGUI::UString &;
%typemap(in, numinputs=0) MyGUI::UString &OUTPUT (MyGUI::UString temp)
%{ $1 = &temp; %}
%typemap(argout) MyGUI::UString &OUTPUT (std::string temps)
%{ temps = $1.asUTF8(), sq_pushstring(v,temps.data(),temps.size()); SWIG_arg++;%}
%typemap(in) MyGUI::UString &INOUT =const MyGUI::UString &;
%typemap(argout) MyGUI::UString &INOUT = MyGUI::UString &OUTPUT;

/*
For const MyGUI::UString* and MyGUI::UString* is not clear
is this a pointer or an array?

Therefore just leaving it as is
(there is some rough code below which could be used if needed

// SWIG wraps const ref's as pointer
// typemaps to deal with this and const ptrs
%typemap(in,checkfn="lua_isstring")
	const MyGUI::UString& INPUT(MyGUI::UString temp),
	const MyGUI::UString* INPUT(MyGUI::UString temp)
%{temp=(char*)lua_tostring(L, $input); $1=&temp;%}
%typemap(out) const MyGUI::UString&, const MyGUI::UString*
%{  lua_pushstring(L,$1->c_str()); SWIG_arg++;%}

// the non-const pointer version
%typemap(in) MyGUI::UString *INPUT=const MyGUI::UString *INPUT;
%typemap(in, numinputs=0) MyGUI::UString *OUTPUT (MyGUI::UString temp)
%{ $1 = &temp; %}
%typemap(argout) MyGUI::UString *OUTPUT
%{  lua_pushstring(L,$1->c_str()); SWIG_arg++;%}
%typemap(in) MyGUI::UString *INOUT = MyGUI::UString *INPUT;
%typemap(argout) MyGUI::UString *INOUT = MyGUI::UString *OUTPUT;

*/

/*
A really cut down version of the string class

This provides basic mapping of squirrel strings <-> MyGUI::UString
and little else
(the MyGUI::UString has a lot of unneeded functions anyway)

note: no fn's taking the const string&
as this is overloaded by the const char* version
*/
namespace MyGUI {

    class UString {
      public:
        UString();
        UString(const char*);
        //UString(const UString&);
        unsigned int size() const;
        unsigned int length() const;
        bool empty() const;
        // no support for operator[]
        const char* c_str()const;
        const char* data()const;
        // assign does not return a copy of this object
        // (no point in a scripting language)
        void assign(const char*);
        //void assign(const string&);
        // no support for all the other features
        // its probably better to do it in squirrel
    };
}
